package com.gitee.wsl.scheduler.job.runtime

import com.gitee.wsl.concurrent.scheduler.Scheduler
import com.gitee.wsl.platform.scheduler.computationScheduler
import com.gitee.wsl.concurrent.scheduler.ext.asCoroutineDispatcher
import com.gitee.wsl.platform.scheduler.singleScheduler
import com.gitee.wsl.scheduler.job.KJob
import com.gitee.wsl.scheduler.job.bean.JobExecutionType
import com.gitee.wsl.concurrent.service.DefaultScheduledExecutorService
import com.gitee.wsl.concurrent.service.ScheduledExecutorService
import kotlinx.coroutines.CoroutineDispatcher


interface JobExecutors {
    val executorService: ScheduledExecutorService
    val dispatchers: Map<JobExecutionType, DispatcherWrapper>

    fun shutdown() {
        dispatchers.values.forEach { it.shutdown() }
        executorService.shutdown()
    }
}

//internal class DefaultJobExecutors(config: KJob.Configuration) : JobExecutors {
//    override val executorService: ScheduledExecutorService by lazy { ScheduledThreadPoolExecutor(3) }
//    override val dispatchers: Map<JobExecutionType, DispatcherWrapper> = mapOf(
//        JobExecutionType.BLOCKING to object : DispatcherWrapper {
//            private val executor = Executors.newFixedThreadPool(config.blockingMaxJobs) { r -> Thread(r, "kjob-blocking-executor") } as ThreadPoolExecutor
//            override fun canExecute(): Boolean = executor.activeCount < executor.corePoolSize
//            override val coroutineDispatcher: CoroutineDispatcher = executor.asCoroutineDispatcher()
//            override fun shutdown() {
//                executor.shutdown()
//            }
//        },
//        JobExecutionType.NON_BLOCKING to object : DispatcherWrapper {
//            private val executor = Executors.newWorkStealingPool(config.nonBlockingMaxJobs) as ForkJoinPool
//            override fun canExecute(): Boolean = executor.activeThreadCount < executor.parallelism
//            override val coroutineDispatcher: CoroutineDispatcher = executor.asCoroutineDispatcher()
//            override fun shutdown() {
//                executor.shutdown()
//            }
//        }
//    )
//}

internal class DefaultJobExecutors(
    config: KJob.Configuration,
    val scheduler: Scheduler =  Scheduler.computationScheduler
) : JobExecutors {

    override val executorService: ScheduledExecutorService by lazy { DefaultScheduledExecutorService(scheduler) }

    override val dispatchers: Map<JobExecutionType, DispatcherWrapper> = mapOf(
        JobExecutionType.BLOCKING to object : DispatcherWrapper {
            val scheduler = Scheduler.singleScheduler
            private val executor = scheduler.newExecutor()
            override fun canExecute(): Boolean = !executor.isDisposed

            override val coroutineDispatcher: CoroutineDispatcher = scheduler.asCoroutineDispatcher()
            override fun shutdown() {
                scheduler.destroy()
            }
        },
        JobExecutionType.NON_BLOCKING to object : DispatcherWrapper {
            val scheduler = Scheduler.computationScheduler
            private val executor = scheduler.newExecutor()
            override fun canExecute(): Boolean = !executor.isDisposed

            override val coroutineDispatcher: CoroutineDispatcher = scheduler.asCoroutineDispatcher()
            override fun shutdown() {
                scheduler.destroy()
            }
        },
    )
}